package com.verlet.gateway.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.List;

import static com.verlet.gateway.filter.AuthorizeGatewayFilter.AUTHORIZE_TOKEN;
import static com.verlet.gateway.filter.AuthorizeGatewayFilter.AUTHORIZE_UID;

/**
 * 继承AbstractGatewayFilterFactory类
 * 可以配置文件配置
 *
 * @author verlet
 */
@Slf4j
@Component
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private final static String WITH_PARAMS = "withParams";

    public AuthorizeGatewayFilterFactory() {
        super(AuthorizeGatewayFilterFactory.Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {

        return (exchange, chain) -> {
            log.info("====>自定义FilterFactory过滤器执行。 config==> {}", config);
            if (config.getWithParams()) {
                ServerHttpRequest request = exchange.getRequest();
                HttpHeaders headers = request.getHeaders();
                String token = headers.getFirst(AUTHORIZE_TOKEN);
                String uid = headers.getFirst(AUTHORIZE_UID);
                if (token == null) {
                    token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
                }
                if (uid == null) {
                    uid = request.getQueryParams().getFirst(AUTHORIZE_UID);
                }

                ServerHttpResponse response = exchange.getResponse();
                if (StringUtils.isAnyBlank(token, uid)) {
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    return response.setComplete();
                }

                assert uid != null;
                String authToken = stringRedisTemplate.opsForValue().get(uid);
                if (authToken == null || !authToken.equals(token)) {
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    return response.setComplete();
                }
            }
            return chain.filter(exchange).then(Mono.fromRunnable(() -> log.info("=======>自定义FilterFactory过滤器执行后操作。==========")));
        };
    }

    /**
     * 可以直接简写  - Authorize=true
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList(WITH_PARAMS);
    }


    public static class Config {

        /**
         * 是否需要验证
         */
        private boolean withParams;

        public boolean getWithParams() {
            return withParams;
        }

        public Config setWithParams(boolean withParams) {
            this.withParams = withParams;
            return this;
        }

        @Override
        public String toString() {
            return "Config{" +
                    "withParams=" + withParams +
                    '}';
        }
    }
}
